home *** CD-ROM | disk | FTP | other *** search
/ Software 2000 / Software 2000 Volume 1 (Disc 1 of 2).iso / utilities / u287.dms / in.adf / Source / Evaluate.p < prev    next >
Encoding:
Text File  |  1991-05-16  |  50.0 KB  |  2,019 lines

  1. External;
  2.  
  3. {$I "Pascal.i"}
  4.  
  5.     Function GetLabel : Integer;
  6.         external;
  7.     Function GetFramePointer(Ref : Integer) : Regs;
  8.         External;
  9.     Function BaseType(b : TypePtr): TypePtr;
  10.         external;
  11.     Function SimpleType(t : TypePtr) : Boolean;
  12.         external;
  13.     Function NumberType(t : TypePtr) : Boolean;
  14.         External;
  15.     Function TypeCheck(l, r : TypePtr) : Boolean;
  16.         External;
  17.     Function ExpressionTree : ExprPtr;
  18.         External;
  19.     Procedure Optimize(Expr : ExprPtr);
  20.         External;
  21.     Procedure Error(msg : String);
  22.         External;
  23.     Function GetReference : ExprPtr;
  24.         External;
  25.     Function Match(s : Symbols) : Boolean;
  26.         External;
  27.     Function PromoteTypeA(Expr : ExprPtr; TP : TypePtr) : ExprPtr;
  28.         External;
  29.     Function MakeNode(s : Symbols; L, R : ExprPtr; TP : TypePtr;
  30.                 Val : Integer) : ExprPtr;
  31.         External;
  32.     Procedure PopStackSpace(Amount : Integer);
  33.          External;
  34.     Procedure Out_Operation0(op : OpCodes);
  35.         External;
  36.     Procedure Out_Operation1(op : OpCodes; Size : Byte;
  37.                     EA : EAModes; Reg : Regs);
  38.         External;
  39.     Procedure Out_Operation2(op : OpCodes; Size : Byte;
  40.                     SrcEA : EAModes; SrcReg : Regs;
  41.                     DestEA : EAModes; DestReg : Regs);
  42.         External;
  43.     Procedure Out_Extension(Ext : Integer);
  44.         External;
  45.  
  46.  
  47.  
  48. Function RegisterInUse(reg : Regs) : Boolean;
  49. begin
  50.     RegisterInUse := (UsedRegs and (1 shl Ord(reg))) <> 0;
  51. end;
  52.  
  53. Procedure MarkRegister(reg : Regs);
  54. begin
  55. {    if not RegisterInUse(reg) then
  56.         Writeln(OutFile, '*  ', RN[reg], ': used'); }
  57.     UsedRegs := UsedRegs or (1 shl Ord(reg));
  58. end;
  59.  
  60. Procedure UnmarkRegister(reg : Regs);
  61. begin
  62. {    if RegisterInUse(reg) then
  63.         Writeln(OutFile, '*  ', RN[reg], ': free'); }
  64.     UsedRegs := UsedRegs and (not (1 shl Ord(reg)));
  65. end;
  66.  
  67. Procedure SaveRegisterToStack(reg : Regs);
  68. begin
  69.     Out_Operation1(op_PUSH,4,ea_Register,reg);
  70.     StackLoad := StackLoad + 4;
  71.     UnmarkRegister(reg);
  72. end;
  73.  
  74. Procedure RestoreRegisterFromStack(reg : Regs);
  75. begin
  76.     Out_Operation1(op_POP,4,ea_Register,reg);
  77.     StackLoad := StackLoad - 4;
  78.     MarkRegister(reg);
  79. end;
  80.  
  81. Procedure FreeAllRegisters;
  82. begin
  83.     UsedRegs := 0;
  84.     NextDataRegister := d7;
  85.     NextAddressRegister := a3;
  86. end;
  87.  
  88. Procedure AllocateDataRegister(var reg : Regs; var Stacked : Boolean);
  89. begin
  90.     if NextDataRegister >= d2 then begin
  91.     reg := NextDataRegister;
  92.     Stacked := False;
  93.     Dec(NextDataRegister);
  94.     end else begin
  95.     SaveRegisterToStack(d7);
  96.     reg := d7;
  97.     Stacked := True;
  98.     end;
  99. end;
  100.  
  101. Procedure DeallocateDataRegister(reg : Regs; Stacked : Boolean);
  102. begin
  103.     if Stacked then
  104.     RestoreRegisterFromStack(reg)
  105.     else begin
  106.     UnmarkRegister(reg);
  107.     Inc(NextDataRegister);
  108.     end;
  109. end;
  110.  
  111. Procedure AllocateAddressRegister(var reg : Regs; var Stacked : Boolean);
  112. begin
  113.     if NextAddressRegister >= a0 then begin
  114.     reg := NextAddressRegister;
  115.     Stacked := False;
  116.     Dec(NextAddressRegister);
  117.     end else begin
  118.     SaveRegisterToStack(a3);
  119.     reg := a3;
  120.     Stacked := True;
  121.     end;
  122. end;
  123.  
  124.  
  125. Procedure DeallocateAddressRegister(reg : Regs; Stacked : Boolean);
  126. begin
  127.     if Stacked then
  128.     RestoreRegisterFromStack(reg)
  129.     else begin
  130.     UnmarkRegister(reg);
  131.     Inc(NextAddressRegister);
  132.     end;
  133. end;
  134.  
  135. Function TemporaryData : Regs;
  136. var
  137.     reg : Regs;
  138. begin
  139.     if not RegisterInUse(d0) then
  140.     TemporaryData := d0;
  141.     if not RegisterInUse(d1) then
  142.     TemporaryData := d1;
  143.     for reg := d7 downto d2 do begin
  144.     if not RegisterInUse(reg) then
  145.         TemporaryData := reg;
  146.     end;
  147.     TemporaryData := a7;
  148. end;
  149.  
  150. Function TemporaryAddress : Regs;
  151. var
  152.     reg : Regs;
  153. begin
  154.     for reg := a0 to a3 do begin
  155.     if not RegisterInUse(reg) then
  156.         TemporaryAddress := reg;
  157.     end;
  158.     TemporaryAddress := a7;
  159. end;
  160.  
  161.  
  162. Procedure SaveAllRegisters;
  163. var
  164.     reg : Regs;
  165. begin
  166.     if (UsedRegs and $0FFF) <> 0 then begin
  167.     Out_Operation2(op_MOVEM,4,ea_RegList,a7,ea_PreDec,a7);
  168.     Out_Extension(UsedRegs and $0FFF);
  169.  
  170.     for reg := d0 to a3 do begin
  171.         if RegisterInUse(reg) then begin
  172.         UnmarkRegister(reg);
  173.         StackLoad := StackLoad + 4;
  174.         end;
  175.     end;
  176.     end;
  177. end;
  178.  
  179.  
  180. Procedure RestoreAllRegisters;
  181. var
  182.     reg : Regs;
  183. begin
  184.     if (UsedRegs and $0FFF) <> 0 then begin
  185.     Out_Operation2(op_MOVEM,4,ea_PostInc,a7,ea_RegList,a7);
  186.     Out_Extension(UsedRegs and $0FFF);
  187.  
  188.     for reg := d0 to a3 do begin
  189.         if RegisterInUse(reg) then
  190.         StackLoad := StackLoad - 4;
  191.     end;
  192.     end;
  193. end;
  194.  
  195.  
  196. Procedure SaveScratchRegisters;
  197.  
  198.     Procedure DoReg(reg : Regs);
  199.     begin
  200.     if RegisterInUse(reg) then begin
  201.         StackLoad := StackLoad + 4;
  202.         UnmarkRegister(reg);
  203.     end;
  204.     end;
  205.  
  206. begin
  207.     if (UsedRegs and $0303) <> 0 then begin
  208.     Out_Operation2(op_MOVEM,4,ea_RegList,a7,ea_PreDec,a7);
  209.     Out_Extension(UsedRegs and $0303);  { d0, d1, a0 and a1 }
  210.     DoReg(d0);
  211.     DoReg(d1);
  212.     DoReg(a0);
  213.     DoReg(a1);
  214.     end;
  215. end;
  216.  
  217.  
  218. Procedure RestoreScratchRegisters;
  219. var
  220.     WroteAny : Boolean;
  221.  
  222.     Procedure DoReg(reg : Regs);
  223.     begin
  224.     if RegisterInUse(reg) then
  225.         StackLoad := StackLoad - 4;
  226.     end;
  227.  
  228. begin
  229.     if (UsedRegs and $0303) <> 0 then begin
  230.     Out_Operation2(op_MOVEM,4,ea_PostInc,a7,ea_RegList,a7);
  231.     Out_Extension(UsedRegs and $0303); { d0, d1, a0 and a1 }
  232.  
  233.     DoReg(d0);
  234.     DoReg(d1);
  235.     DoReg(a0);
  236.     DoReg(a1);
  237.     end;
  238. end;
  239.  
  240.  
  241. {
  242.     This routine is used to add a constant value to any register.
  243.     It does so in the most efficient way, to wit:
  244.  
  245.     Add  0 < x <= 8 to An    : addq.w #x,An
  246.     Add word to An        : lea word(An),An
  247.     Add  9 <= x <= 16 to An    : addq.w #8,An
  248.                   addq.w #x-8,An
  249.  
  250.     Subtractions work the same way.  For data registers, A68k will
  251.     handle optimizations, so they just work normally.
  252. }
  253.  
  254. Procedure AddConstant(Amount : Integer; ToReg : Regs; Size : Byte);
  255. begin
  256.     if Amount = 0 then
  257.     return;
  258.     if ToReg >= a0 then begin
  259.     case Amount of
  260.       1..8 :
  261.         begin
  262.         Out_Operation2(op_ADDQ,2,ea_Constant,a7,ea_Register,ToReg);
  263.         Out_Extension(Amount);
  264.         end;
  265.  
  266.       -8..-1 :
  267.         begin
  268.         Out_Operation2(op_SUBQ,2,ea_Constant,a7,ea_Register,ToReg);
  269.         Out_Extension(-Amount);
  270.         end;
  271.       -32768..32767 :
  272.         begin
  273.         Out_Operation2(op_LEA,3,ea_Index,ToReg,ea_Register,ToReg);
  274.         Out_Extension(Amount);
  275.         end;
  276.     else begin
  277.          if Amount > 0 then begin
  278.              Out_Operation2(op_ADDA,4,ea_Constant,a7,ea_Register,ToReg);
  279.              Out_Extension(Amount);
  280.          end else begin
  281.              Out_Operation2(op_SUBA,4,ea_Constant,a7,ea_Register,ToReg);
  282.              Out_Extension(-Amount);
  283.          end;
  284.          end;
  285.     end;
  286.     end else begin
  287.     if Amount > 0 then begin
  288.         Out_Operation2(op_ADD,Size,ea_Constant,a7,ea_Register,ToReg);
  289.         Out_Extension(Amount);
  290.     end else begin
  291.         Out_Operation2(op_SUB,Size,ea_Constant,a7,ea_Register,ToReg);
  292.         Out_Extension(-Amount);
  293.     end;
  294.     end;
  295. end;
  296.  
  297. {
  298.     If the expression Expr is a variable that can be referenced as one
  299.     of the arguments of an assembly command, return true.  Return false
  300.     if the expression requires calculations.
  301.  
  302.     Global variables, typed constants, local variables, and value
  303.     parameters return true if they are simple types (i.e. can be held
  304.     in a register).  Reference parameters, sub-expressions, arrays, etc.
  305.     all return false.  Field references return true if the record reference
  306.     is a simple reference.
  307. }
  308.  
  309. Function SimpleReference(Expr : ExprPtr) : Boolean;
  310. var
  311.     ID : IDPtr;
  312. begin
  313.     if not SimpleType(Expr^.EType) then
  314.     SimpleReference := False;    { Requires a memory reference }
  315.  
  316.     if Expr^.Kind = Var1 then begin
  317.     ID := IDPtr(Expr^.Value);
  318.     case ID^.Object of
  319.       global,
  320.       typed_const : SimpleReference := True;
  321.       local,
  322.       valarg : SimpleReference := (ID^.Level = CurrentBlock^.Level) or
  323.                     (ID^.Level <= 1);
  324.     else
  325.         SimpleReference := False;
  326.     end;
  327.     end;
  328.  
  329.     if Expr^.Kind = period1 then
  330.         if Expr^.Left^.Kind = var1 then
  331.             SimpleReference := SimpleReference(Expr^.Left);
  332.  
  333.     SimpleReference := False;
  334. end;
  335.  
  336.  
  337. {
  338.     Given that the expression satifies "SimpleReference" above,
  339.     write the actual value reference.
  340. }
  341.  
  342. Procedure GetSimpleReference(var EA : EAModes; var Reg : Regs;
  343.                 var Ext1, Ext2 : Integer; Expr : ExprPtr);
  344. var
  345.     ID : IDPtr;
  346.     WasField : Boolean;
  347. begin
  348.     if Expr^.Kind = period1 then begin
  349.     WasField := True;
  350.     Ext2 := Expr^.Value;
  351.     Expr := Expr^.Left;
  352.     end else begin
  353.     WasField := False;
  354.     Ext2 := 0;
  355.     end;
  356.  
  357.     Reg := a7;
  358.     ID := IDPtr(Expr^.Value);
  359.     case ID^.Object of
  360.       typed_const,
  361.       global  : begin
  362.             if WasField then
  363.             EA := ea_Offset
  364.             else
  365.                 EA := ea_Global;
  366.             Ext1 := Integer(ID);
  367.         end;
  368.       valarg,
  369.       local   : begin
  370.             EA := ea_Index;
  371.             Ext1 := ID^.Offset + Ext2;
  372.             Reg := a5;
  373.         end;
  374.     end;
  375. end;
  376.  
  377. Procedure WriteSimpleSource(Expr : ExprPtr; op : OpCodes; Size : Byte;
  378.                 DestEA : EAModes; DestReg : Regs);
  379. var
  380.     SrcEA  : EAModes;
  381.     SrcReg : Regs;
  382.     Ext1,
  383.     Ext2   : Integer;
  384. begin
  385.     GetSimpleReference(SrcEA, SrcReg, Ext1, Ext2, Expr);
  386.     Out_Operation2(op, Size, SrcEA, SrcReg, DestEA, DestReg);
  387.     Out_Extension(Ext1);
  388.     if SrcEA = ea_Offset then
  389.     Out_Extension(Ext2);
  390. end;
  391.  
  392. Procedure WriteSimpleDest(Expr : ExprPtr; op : OpCodes; Size : Byte;
  393.                 SrcEA : EAModes; SrcReg : Regs;
  394.                 SExt1, SExt2 : Integer);
  395. var
  396.     DestEA  : EAModes;
  397.     DestReg : Regs;
  398.     Ext1,
  399.     Ext2    : Integer;
  400. begin
  401.     GetSimpleReference(DestEA, DestReg, Ext1, Ext2, Expr);
  402.     Out_Operation2(op, Size, SrcEA, SrcReg, DestEA, DestReg);
  403.     if Extensions[SrcEA] >= 1 then begin
  404.     Out_Extension(SExt1);
  405.     if Extensions[SrcEA] >= 2 then
  406.         Out_Extension(SExt2);
  407.     end;
  408.     Out_Extension(Ext1);
  409.     if DestEA = ea_Offset then
  410.     Out_Extension(Ext2);
  411. end;
  412.  
  413. Procedure WriteSimpleSingle(Expr : ExprPtr; op : OpCodes; Size : Byte);
  414. var
  415.     EA : EAModes;
  416.     Reg : Regs;
  417.     Ext1,
  418.     Ext2 : Integer;
  419. begin
  420.     GetSimpleReference(EA, Reg, Ext1, Ext2, Expr);
  421.     Out_Operation1(op, Size, EA, Reg);
  422.     Out_Extension(Ext1);
  423.     if EA = ea_Offset then
  424.     Out_Extension(Ext2);
  425. end;
  426.  
  427.  
  428. Procedure Evaluate(Expr : ExprPtr; ToReg : Regs);
  429.     forward;
  430.  
  431. Procedure EvalAddress(Expr : ExprPtr; ToReg : Regs);
  432.     forward;
  433.  
  434.  
  435.  
  436. Procedure ConstantShiftLeft(Shifts : Byte; ToReg : Regs; Size : Byte);
  437. begin
  438.     Shifts := Shifts and 31;
  439.     while Shifts > 0 do begin
  440.     case Shifts of
  441.       1 :    begin
  442.             Out_Operation2(op_ADD,Size,ea_Register,ToReg,
  443.                         ea_Register,ToReg);
  444.             Shifts := 0;
  445.         end;
  446.       2..7 :
  447.         begin
  448.             Out_Operation2(op_LSL,Size,ea_Constant,a7,ea_Register,ToReg);
  449.             Out_Extension(Shifts);
  450.             Shifts := 0;
  451.         end;
  452.       8..15 :
  453.         if Size = 1 then
  454.             Shifts := 0
  455.         else begin
  456.             Out_Operation2(op_LSL,Size,ea_Constant,a7,ea_Register,ToReg);
  457.             Out_Extension(8);
  458.             Shifts := Shifts - 8;
  459.         end;
  460.       16..31 :
  461.         if Size <> 4 then
  462.             Shifts := 0
  463.         else begin
  464.             Out_Operation1(op_SWAP,3,ea_Register,ToReg);
  465.             Out_Operation1(op_CLR,2,ea_Register,ToReg);
  466.             Shifts := Shifts - 16;
  467.         end;
  468.     end;
  469.     end;
  470. end;
  471.  
  472.  
  473. Procedure ConstantShiftRight(Op : OpCodes; Shifts : Byte;
  474.                              ToReg : Regs; Size : Byte);
  475. begin
  476.     Shifts := Shifts and 31;
  477.     while Shifts > 0 do begin
  478.     case Shifts of
  479.       1..7 :
  480.         begin
  481.             Out_Operation2(Op,Size,ea_Constant,a7,
  482.                         ea_Register,ToReg);
  483.             Out_Extension(Shifts);
  484.             Shifts := 0;
  485.         end;
  486.       8..15 :
  487.         if Size = 1 then
  488.             Shifts := 0
  489.         else begin
  490.             Out_Operation2(Op,Size,ea_Constant,a7,
  491.                         ea_Register,ToReg);
  492.             Out_Extension(8);
  493.             Shifts := Shifts - 8;
  494.         end;
  495.       16..31 :
  496.         if Size <> 4 then
  497.             Shifts := 0
  498.         else if Op = op_LSR then begin
  499.             Out_Operation1(op_CLR,2,ea_Register,ToReg);
  500.             Out_Operation1(op_SWAP,3,ea_Register,ToReg);
  501.             Shifts := Shifts - 16;
  502.         end else begin
  503.             Out_Operation1(op_SWAP,3,ea_Register,ToReg);
  504.             Out_Operation1(op_EXT,4,ea_Register,ToReg);
  505.             Shifts := Shifts - 16;
  506.         end;
  507.     end;
  508.     end;
  509. end;
  510.  
  511.  
  512. {
  513.     Push each expression in the list onto the stack, then return
  514.     the total size (in bytes) of the stack load.  This routine
  515.     assumes that all the scratch registers are free.
  516. }
  517.  
  518.  
  519. Function PushArguments(Expr : ExprPtr; ToReg : Regs) : Integer;
  520. var
  521.     Argument : ExprPtr;
  522.     Formal   : IDPtr;
  523.     Total    : Integer;
  524.     Stag     : Byte;
  525.     lab,
  526.     VarSize  : Integer;
  527. begin
  528.     Argument := Expr^.Left;
  529.     Formal   := IDPtr(Expr^.Value);
  530.     Formal   := Formal^.Param;
  531.     Total    := 0;
  532.     while (Argument <> Nil) and (Formal <> Nil) do begin
  533.     VarSize := Formal^.VType^.Size;
  534.     if Formal^.Object = valarg then begin
  535.         STag := VarSize;
  536.         if STag = 1 then
  537.         STag := 2;
  538.         Total := Total + VarSize;
  539.         if SimpleType(Formal^.VType) then begin
  540.         if Argument^.Kind = Const1 then begin
  541.             if STag = 4 then begin
  542.             Out_Operation1(op_PEA,3,ea_Absolute,a7);
  543.             Out_Extension(Argument^.Value);
  544.             end else begin
  545.             Out_Operation1(op_PUSH,2,ea_Constant,a7);
  546.             Out_Extension(Argument^.Value);
  547.             end;
  548.         end else if SimpleReference(Argument) and
  549.                 (Argument^.EType^.Size = STag) then begin
  550.             WriteSimpleSingle(Argument,op_PUSH,STag);
  551.         end else begin
  552.             Evaluate(Argument,ToReg);
  553.             Out_Operation1(op_PUSH,STag,ea_Register,ToReg);
  554.             UnmarkRegister(ToReg);
  555.         end;
  556.         StackLoad := StackLoad + VarSize;
  557.         if Odd(Total) then begin
  558.             Inc(StackLoad);
  559.             Inc(Total);
  560.         end;
  561.         end else begin
  562.         Evaluate(Argument,a0);
  563.         VarSize := Formal^.VType^.Size;
  564.  
  565.         Out_Operation2(op_MOVE,4,ea_Register,a7,ea_Register,a1);
  566.         AddConstant(-VarSize, a1, 4);
  567.         Out_Operation2(op_MOVE,4,ea_Constant,a7,ea_Register,d1);
  568.         Out_Extension(Pred(VarSize));
  569.  
  570.         lab := GetLabel();
  571.         Out_Operation1(op_LABEL,3,ea_Label,a7);
  572.         Out_Extension(lab);
  573.         Out_Operation2(op_MOVE,1,ea_PostInc,a0,ea_PostInc,a1);
  574.         Out_Operation2(op_DBRA,3,ea_Register,d1,ea_Label,a7);
  575.         Out_Extension(lab);
  576.  
  577.         AddConstant(-VarSize, a7, 4);
  578.         StackLoad := StackLoad + VarSize;
  579.         UnmarkRegister(a0);
  580.         end;
  581.     end else begin { reference parameter }
  582.         EvalAddress(Argument, a0);
  583.         Out_Operation1(op_PUSH,4,ea_Register,a0);
  584.         StackLoad := StackLoad + 4;
  585.         Total := Total + 4;
  586.         UnmarkRegister(a0);
  587.     end;
  588.     Argument := Argument^.Next;
  589.     Formal := Formal^.Next;
  590.     end;
  591.     PushArguments := Total;
  592. end;
  593.  
  594.  
  595. Function PushFrame(Callee : Integer) : Integer;
  596. var
  597.     Caller : Integer;
  598. begin
  599.     if Callee <= 1 then { global-level routines, which include externs }
  600.     PushFrame := 0
  601.     else begin
  602.     Caller := Pred(CurrentBlock^.Level);
  603.     if Callee = Caller + 1 then { calling child procedure }
  604.         Out_Operation1(op_PUSH,4,ea_Register,a5)
  605.     else if Callee = Caller then begin { same level }
  606.         Out_Operation1(op_PUSH,4,ea_Index,a5);
  607.         Out_Extension(8);
  608.     end else begin
  609.         Out_Operation2(op_MOVE,4,ea_Index,a5,ea_Register,a4);
  610.         Out_Extension(8);
  611.         Caller := Pred(Caller);
  612.         while Caller > Callee do begin
  613.         Out_Operation2(op_MOVE,4,ea_Index,a4,ea_Register,a4);
  614.         Out_Extension(8);
  615.         Caller := Pred(Caller);
  616.         end;
  617.         Out_Operation1(op_PUSH,4,ea_Index,a4);
  618.         Out_Extension(8);
  619.     end;
  620.     StackLoad := StackLoad + 4;
  621.     PushFrame := 4;
  622.     end;
  623. end;
  624.  
  625. {  Load the address of Expr into ToReg.  The Expr must be a valid
  626.    variable reference, not a general expression. }
  627.  
  628. Procedure EvalAddress(Expr : ExprPtr; ToReg : Regs);
  629. var
  630.     Stacked  : Boolean;
  631.     OtherReg : Regs;
  632.     ID       : IDPtr;
  633.     Reg      : Regs;
  634.     WithInfo : WithRecPtr;
  635.     SavedRegs: Integer;
  636. begin
  637.     case Expr^.Kind of
  638.       var1 : begin
  639.         ID := IDPtr(Expr^.Value);
  640.         case ID^.Object of
  641.           global,
  642.           typed_const,
  643.           func,
  644.           proc  :
  645.             begin
  646.                 Out_Operation2(op_MOVE,4,ea_Address,a7,ea_Register,ToReg);
  647.                 Out_Extension(Integer(ID));
  648.             end;
  649.           local,
  650.           valarg :
  651.             begin
  652.                 Reg := GetFramePointer(ID^.Level);
  653.                 if ToReg >= a0 then begin
  654.                 Out_Operation2(op_LEA,3,ea_Index,Reg,ea_Register,ToReg);
  655.                 Out_Extension(ID^.Offset);
  656.                 end else begin
  657.                 Out_Operation2(op_LEA,3,ea_Index,Reg,ea_Register,a4);
  658.                 Out_Extension(ID^.Offset);
  659.                 Out_Operation2(op_MOVE,4,ea_Register,a4,ea_Register,ToReg);
  660.                 end;
  661.             end;
  662.           refarg :
  663.             begin
  664.                 Reg := GetFramePointer(ID^.Level);
  665.                 Out_Operation2(op_MOVE,4,ea_Index,Reg,ea_Register,ToReg);
  666.                 Out_Extension(ID^.Offset);
  667.             end;
  668.         end;
  669.          end;
  670.       field1  : begin
  671.             ID := IDPtr(Expr^.Value);
  672.             WithInfo := WithRecPtr(Expr^.Left);
  673.             Out_Operation2(op_MOVE,4,ea_Index,a7,ea_Register,ToReg);
  674.             Out_Extension(Stackload - WithInfo^.Offset);
  675.             if ID^.Offset <> 0 then
  676.             AddConstant(ID^.Offset, ToReg, 4);
  677.         end;
  678.       period1 : begin
  679.             EvalAddress(Expr^.Left,ToReg);
  680.             AddConstant(Expr^.Value, ToReg, 4);
  681.                 end;
  682.       carat1 : if Expr^.Left^.EType^.Object = ob_file then begin
  683.            SavedRegs := UsedRegs;
  684.            SaveScratchRegisters;
  685.            Evaluate(Expr^.Left,a0);
  686.            Out_Operation1(op_JSR,3,ea_String,a7);
  687.            Out_Extension(Integer("_p%FilePtr"));
  688.            if IOCheck then begin
  689.             Out_Operation1(op_JSR,3,ea_String,a7);
  690.             Out_Extension(Integer("_p%CheckIO"));
  691.            end;
  692.            if ToReg <> a0 then
  693.             Out_Operation2(op_MOVE,4,ea_Register,a0,ea_Register,ToReg);
  694.            UsedRegs := SavedRegs;
  695.            RestoreScratchRegisters;
  696.         end else
  697.            Evaluate(Expr^.Left,ToReg);
  698.       leftbrack1 : 
  699.         with Expr^ do begin
  700.             if Left^.EType = StringType then
  701.             Evaluate(Left, ToReg)
  702.             else
  703.             EvalAddress(Left,ToReg);
  704.             if SimpleReference(Right) and (not RangeCheck) then begin
  705.             WriteSimpleSource(Right,op_ADD,4,ea_Register,ToReg);
  706.             { If it's a simple reference it must be an Integer}
  707.             end else begin
  708.             AllocateDataRegister(OtherReg, Stacked);
  709.             Evaluate(Right, OtherReg);
  710.             if RangeCheck and (Left^.EType <> StringType) then begin
  711.                 Out_Operation1(op_PEA,3,ea_Absolute,a7);
  712.                 Out_Extension((Left^.EType^.Upper -
  713.                        Left^.EType^.Lower) *
  714.                        Left^.EType^.SubType^.Size);
  715.                 Out_Operation1(op_PUSH,4,ea_Register,OtherReg);
  716.                 Out_Operation1(op_JSR,3,ea_String,a7);
  717.                 Out_Extension(Integer("_p%CheckRange"));
  718.             end;
  719.             Out_Operation2(op_ADD,4,ea_Register,OtherReg,
  720.                         ea_Register,ToReg);
  721.             DeallocateDataRegister(OtherReg,Stacked);
  722.             end;
  723.         end;
  724.       type1 : EvalAddress(Expr^.Left, ToReg);
  725.     else
  726.         Writeln('Error in EvalAddress : ', Ord(Expr^.Kind));
  727.     end;
  728.     MarkRegister(ToReg);
  729. end;
  730.  
  731.  
  732. Procedure Evaluate(Expr : ExprPtr; ToReg : Regs);
  733. var
  734.     op : Symbols;
  735.     TagModel : String;
  736.  
  737.     Procedure ConstantOperation(op : OpCodes; STag : Byte;
  738.                     Value : Integer; ToReg : Regs);
  739.     var
  740.     OtherReg : Regs;
  741.     begin
  742.     OtherReg := TemporaryData;
  743.     if (OtherReg < a0) and (Value <= 127) and (Value >= -128) and
  744.        (STag >= 3) and (Value <> 0) then begin
  745.         Out_Operation2(op_MOVEQ,3,ea_Constant,a7,ea_Register,OtherReg);
  746.         Out_Extension(Value);
  747.         Out_Operation2(op,STag,ea_Register,OtherReg,ea_Register,ToReg);
  748.     end else begin
  749.         Out_Operation2(op, STag, ea_Constant,a7,ea_Register,ToReg);
  750.         Out_Extension(Value);
  751.     end;
  752.     end;
  753.  
  754.  
  755.     Procedure Eval_BinaryFloat(offset : Integer);
  756.     var
  757.     SaveUsed : Integer;
  758.     begin
  759.     SaveUsed := UsedRegs;
  760.     SaveScratchRegisters;
  761.     Evaluate(Expr^.Left, d1);
  762.     Evaluate(Expr^.Right, d0);
  763.     if not MathLoaded then begin
  764.         Out_Operation2(op_MOVE,4,ea_String,a7,ea_Register,a6);
  765.         Out_Extension(Integer("_p%MathBase"));
  766.         MathLoaded := True;
  767.     end;
  768.     Out_Operation1(op_JSR,3,ea_Index,a6);
  769.     Out_Extension(Offset);
  770.     if ToReg <> d0 then
  771.         Out_Operation2(op_MOVE,4,ea_Register,d0,ea_Register,ToReg);
  772.     UsedRegs := SaveUsed;
  773.     RestoreScratchRegisters;
  774.     end;
  775.  
  776.  
  777.     Procedure Eval_UnaryFloat(offset : Integer);
  778.     var
  779.     SaveUsed : Integer;
  780.     begin
  781.     SaveUsed := UsedRegs;
  782.     SaveScratchRegisters;
  783.     Evaluate(Expr^.Left, d0);
  784.     if not MathLoaded then begin
  785.         Out_Operation2(op_MOVE,4,ea_String,a7,ea_Register,a6);
  786.         Out_Extension(Integer("_p%MathBase"));
  787.         MathLoaded := True;
  788.     end;
  789.     Out_Operation1(op_JSR,3,ea_Index,a6);
  790.     Out_Extension(Offset);
  791.     if ToReg <> d0 then
  792.         Out_Operation2(op_MOVE,4,ea_Register,d0,ea_Register,ToReg);
  793.     UsedRegs := SaveUsed;
  794.     RestoreScratchRegisters;
  795.     end;
  796.  
  797.  
  798.     Procedure Eval_32BitMath(math : String);
  799.     var
  800.     SavedRegs : Integer;
  801.  
  802.     Procedure EvalToStack(Expr : ExprPtr);
  803.      begin
  804.         if Expr^.Kind = Const1 then begin
  805.         Out_Operation1(op_PEA,3,ea_Absolute,a7);
  806.         Out_Extension(Expr^.Value);
  807.         end else if SimpleReference(Expr) then begin
  808.         WriteSimpleSingle(Expr,op_PUSH,4);
  809.         end else begin
  810.         Evaluate(Expr, ToReg);
  811.         Out_Operation1(op_PUSH,4,ea_Register,ToReg);
  812.         end;
  813.         StackLoad := StackLoad + 4;
  814.         UnmarkRegister(ToReg);
  815.     end;
  816.  
  817.     begin
  818.     with Expr^ do begin
  819.         SavedRegs := UsedRegs;
  820.         SaveScratchRegisters;
  821.         EvalToStack(Left);
  822.         EvalToStack(Right);
  823.         Out_Operation1(op_JSR,3,ea_String,a7);
  824.         Out_Extension(Integer(Math));
  825.         if ToReg <> d0 then
  826.         Out_Operation2(op_MOVE,4,ea_Register,d0,ea_Register,ToReg);
  827.         PopStackSpace(8);
  828.         UsedRegs := SavedRegs;
  829.         RestoreScratchRegisters;
  830.     end;
  831.     end;
  832.  
  833.  
  834.     Procedure Eval_BinaryMath(op : OpCodes; UseSize : Boolean);
  835.     { add, sub, or, and, xor }
  836.     var
  837.     OtherReg : Regs;
  838.     Stacked  : Boolean;
  839.     STag     : Byte;
  840.     begin
  841.     with Expr^ do begin
  842.         if UseSize then
  843.         STag := EType^.Size
  844.         else
  845.         STag := 3;
  846.  
  847.         if Left^.Kind = Const1 then begin
  848.         Evaluate(Right, ToReg);
  849.         ConstantOperation(op, STag, Left^.Value, ToReg);
  850.         end else if SimpleReference(Left) and (Op <> op_EOR) then begin
  851.         Evaluate(Right, ToReg);
  852.         WriteSimpleSource(Left,op,STag,ea_Register,ToReg);
  853.         end else begin
  854.         AllocateDataRegister(OtherReg, Stacked);
  855.         Evaluate(Left, OtherReg);
  856.         Evaluate(Right, ToReg);
  857.         Out_Operation2(op,STag,ea_Register,OtherReg,ea_Register,ToReg);
  858.         DeallocateDataRegister(OtherReg, Stacked);
  859.         end;
  860.     end;
  861.     end;
  862.  
  863.  
  864.     Procedure Eval_UnaryMath(op : OpCodes);
  865.     begin
  866.     with Expr^ do begin
  867.         Evaluate(Left, ToReg);
  868.         Out_Operation1(op,EType^.Size,ea_Register,ToReg);
  869.     end;
  870.     end;
  871.  
  872.  
  873.     Procedure Eval_Boolean;
  874.     { Boolean and & or, possibly with short circuits }
  875.     var
  876.     OtherReg : Regs;
  877.     Stacked  : Boolean;
  878.     ShortLab : Integer;
  879.     op       : OpCodes;
  880.     Temp     : ExprPtr;
  881.     begin
  882.     with Expr^ do begin
  883.  
  884.         ShortLab := GetLabel;
  885.  
  886.         if Left^.Kind = Const1 then begin
  887.         Temp := Left;
  888.         Left := Right;
  889.         Right := Temp;
  890.         end;
  891.  
  892.         Evaluate(Left, ToReg);
  893.  
  894.         { If the right half is a constant, it must just be an }
  895.         { 'enabler' - FALSE for OR expressions, or TRUE for   }
  896.         { AND expressions.  Otherwise the expression would    }
  897.         { have optimized out. }
  898.  
  899.         if Right^.Kind = Const1 then
  900.         return;
  901.  
  902.         Out_Operation1(op_TST,1,ea_Register,ToReg);
  903.  
  904.         if Kind = or1 then
  905.         Out_Operation1(op_BNE,3,ea_Label,a7)
  906.         else
  907.         Out_Operation1(op_BEQ,3,ea_Label,a7);
  908.         Out_Extension(ShortLab);
  909.  
  910.         case Kind of
  911.           or1  : op := op_OR;
  912.           and1 : op := op_AND;
  913.         end;
  914.  
  915.         { We know at this point that the left half of the equation }
  916.         { is an enabler - otherwise the branch would have taken    }
  917.         { effect.  Therefore the value of the right half of the    }
  918.         { equation will determine the overall value                }
  919.  
  920.         UnmarkRegister(ToReg);
  921.  
  922.         Evaluate(Right, ToReg);
  923.  
  924.         Out_Operation1(op_LABEL,3,ea_Label,a7);
  925.         Out_Extension(ShortLab);
  926.     end;
  927.     end;
  928.  
  929.  
  930.     Procedure Eval_Comparison;
  931.     var
  932.     STag     : Byte;
  933.     OtherReg : Regs;
  934.     Stacked  : Boolean;
  935.     SaveUsed : Integer;
  936.  
  937.     Function LeftToRight : OpCodes;
  938.     begin
  939.         case Expr^.Kind of
  940.           greater1  : LeftToRight := op_SLT;
  941.           less1    : LeftToRight := op_SGT;
  942.           notgreater1 : LeftToRight := op_SGE;
  943.           notless1    : LeftToRight := op_SLE;
  944.           equal1    : LeftToRight := op_SEQ;
  945.           notequal1    : LeftToRight := op_SNE;
  946.         end;
  947.     end;
  948.  
  949.  
  950.     Function RightToLeft : OpCodes;
  951.     begin
  952.         case Expr^.Kind of
  953.           greater1  : RightToLeft := op_SGT;
  954.           less1    : RightToLeft := op_SLT;
  955.           notgreater1 : RightToLeft := op_SLE;
  956.           notless1    : RightToLeft := op_SGE;
  957.           equal1    : RightToLeft := op_SEQ;
  958.           notequal1    : RightToLeft := op_SNE;
  959.         end;
  960.     end;
  961.  
  962.  
  963.     begin
  964.     with Expr^ do begin
  965.         if Left^.EType = RealType then begin
  966.         SaveUsed := UsedRegs;
  967.         SaveScratchRegisters;
  968.         Evaluate(Expr^.Left, d1);
  969.         Evaluate(Expr^.Right, d0);
  970.         if not MathLoaded then begin
  971.             Out_Operation2(op_MOVE,4,ea_String,a7,ea_Register,a6);
  972.             Out_Extension(Integer("_p%MathBase"));
  973.             MathLoaded := True;
  974.         end;
  975.         Out_Operation1(op_JSR,3,ea_Index,a6);
  976.         Out_Extension(-42);
  977.         Out_Operation1(LeftToRight, 3, ea_Register, d0);
  978.         if ToReg <> d0 then
  979.             Out_Operation2(op_MOVE,4,ea_Register,d0,ea_Register,ToReg);
  980.         UsedRegs := SaveUsed;
  981.         RestoreScratchRegisters;
  982.         end else begin
  983.         STag := Left^.EType^.Size;
  984.  
  985.         if Right^.Kind = Const1 then begin
  986.             Evaluate(Left, ToReg);
  987.             ConstantOperation(op_CMP,STag,Right^.Value,ToReg);
  988.             Out_Operation1(RightToLeft,3,ea_Register,ToReg);
  989.         end else if Left^.Kind = Const1 then begin
  990.             Evaluate(Right, ToReg);
  991.             ConstantOperation(op_CMP,STag, Left^.Value, ToReg);
  992.             Out_Operation1(LeftToRight,3,ea_Register,ToReg);
  993.         end else if SimpleReference(Right) then begin
  994.             Evaluate(Left, ToReg);
  995.             WriteSimpleSource(Right,op_CMP,STag,ea_Register,ToReg);
  996.             Out_Operation1(RightToLeft,3,ea_Register,ToReg);
  997.         end else if SimpleReference(Left) then begin
  998.             Evaluate(Right, ToReg);
  999.             WriteSimpleSource(Left,op_CMP,STag,ea_Register,ToReg);
  1000.             Out_Operation1(LeftToRight,3,ea_Register,ToReg);
  1001.         end else begin
  1002.             AllocateDataRegister(OtherReg, Stacked);
  1003.             Evaluate(Right, OtherReg);
  1004.             Evaluate(Left, ToReg);
  1005.             Out_Operation2(op_CMP,STag,ea_Register,OtherReg,
  1006.                         ea_Register,ToReg);
  1007.             Out_Operation1(RightToLeft,3,ea_Register,ToReg);
  1008.             DeallocateDataRegister(OtherReg, Stacked);
  1009.         end;
  1010.         end;
  1011.     end;
  1012.     end;
  1013.  
  1014.     Procedure LoadIDValue(ID : IDPtr);
  1015.     var
  1016.     STag : Byte;
  1017.     Simp : Boolean;
  1018.     OtherReg : Regs;
  1019.     begin
  1020.     STag := ID^.VType^.Size;
  1021.     Simp := SimpleType(ID^.VType);
  1022.     case ID^.Object of
  1023.       typed_const,
  1024.       global :
  1025.         if Simp then begin
  1026.             Out_Operation2(op_MOVE,STag,ea_Global,a7,ea_Register,ToReg);
  1027.             Out_Extension(Integer(ID));
  1028.         end else begin
  1029.             Out_Operation2(op_MOVE,4,ea_Address,a7,ea_Register,ToReg);
  1030.             Out_Extension(Integer(ID));
  1031.         end;
  1032.       local,
  1033.       valarg :
  1034.         begin
  1035.             OtherReg := GetFramePointer(ID^.Level);
  1036.             if Simp then begin
  1037.             Out_Operation2(op_MOVE,STag,ea_Index,OtherReg,
  1038.                             ea_Register,ToReg);
  1039.             Out_Extension(ID^.Offset);
  1040.             end else begin
  1041.             if ToReg >= a0 then begin
  1042.                 Out_Operation2(op_LEA,3,ea_Index,OtherReg,
  1043.                             ea_Register,ToReg);
  1044.                 Out_Extension(ID^.Offset);
  1045.             end else begin
  1046.                 Out_Operation2(op_LEA,3,ea_Index,OtherReg,
  1047.                             ea_Register,a4);
  1048.                 Out_Extension(ID^.Offset);
  1049.                 Out_Operation2(op_MOVE,4,ea_Register,a4,
  1050.                             ea_Register,ToReg);
  1051.             end;
  1052.             end;
  1053.          end;
  1054.       refarg :
  1055.         begin
  1056.             OtherReg := GetFramePointer(ID^.Level);
  1057.             if Simp then begin
  1058.             Out_Operation2(op_MOVE,4,ea_Index,OtherReg,
  1059.                         ea_Register,a4);
  1060.             Out_Extension(ID^.Offset);
  1061.             Out_Operation2(op_MOVE,STag,ea_Indirect,a4,
  1062.                             ea_Register,ToReg);
  1063.             end else begin
  1064.             Out_Operation2(op_MOVE,4,ea_Index,OtherReg,
  1065.                         ea_Register,ToReg);
  1066.             Out_Extension(ID^.Offset);
  1067.             end;
  1068.         end;
  1069.     end;
  1070.     end;
  1071.  
  1072.  
  1073.     Procedure Eval_Shift;
  1074.     var
  1075.     OtherReg : Regs;
  1076.     Stacked    : Boolean;
  1077.     begin
  1078.     with Expr^ do begin
  1079.         if Right^.Kind = Const1 then begin
  1080.         Evaluate(Left, ToReg);
  1081.         if Kind = shl1 then
  1082.             ConstantShiftLeft(Right^.Value, ToReg, EType^.Size)
  1083.         else
  1084.             ConstantShiftRight(op_LSR,Right^.Value,ToReg,EType^.Size);
  1085.         end else begin
  1086.         AllocateDataRegister(OtherReg, Stacked);
  1087.         Evaluate(Left, ToReg);
  1088.         Evaluate(Right, OtherReg);
  1089.         if Kind = shl1 then
  1090.             Out_Operation2(op_LSL,EType^.Size,ea_Register,OtherReg,
  1091.                             ea_Register,ToReg)
  1092.         else
  1093.             Out_Operation2(op_LSR,EType^.Size,ea_Register,OtherReg,
  1094.                             ea_Register,ToReg);
  1095.         DeallocateDataRegister(OtherReg, Stacked);
  1096.         end;
  1097.     end;
  1098.     end;
  1099.  
  1100.  
  1101.     Procedure Eval_Constant;
  1102.     begin
  1103.     with Expr^ do begin
  1104.         Out_Operation2(op_MOVE,EType^.Size,ea_Constant,a7,
  1105.                         ea_Register,ToReg);
  1106.         Out_Extension(Value);
  1107.     end;
  1108.     end;
  1109.                 
  1110.  
  1111.  
  1112.     { Generate the value of an array reference.  Cases where the index
  1113.       is a constant will not occur - they are converted to period1 nodes
  1114.       in Expr.p and Optimize.p }
  1115.  
  1116.     Procedure Eval_ArrayReference;
  1117.     var
  1118.     AReg,
  1119.     DReg : Regs;
  1120.     Stacked : Boolean;
  1121.     begin
  1122.     with Expr^ do begin
  1123.         if ToReg >= a0 then
  1124.         AReg := ToReg
  1125.         else
  1126.         AllocateAddressRegister(AReg, Stacked);
  1127.         if Left^.EType = StringType then
  1128.         Evaluate(Left, AReg)
  1129.         else
  1130.         EvalAddress(Left, AReg);
  1131.         if SimpleReference(Right) and (not RangeCheck) then begin
  1132.         WriteSimpleSource(Right,op_ADDA,4,ea_Register,AReg);
  1133.         if SimpleType(EType) then
  1134.             Out_Operation2(op_MOVE,EType^.Size,ea_Indirect,AReg,
  1135.                             ea_Register,ToReg)
  1136.         else if AReg <> ToReg then
  1137.             Out_Operation2(op_MOVE,4,ea_Register,AReg,
  1138.                         ea_Register,ToReg);
  1139.         if AReg <> ToReg then
  1140.             DeallocateAddressRegister(AReg, Stacked);
  1141.         end else begin
  1142.         if ToReg < a0 then
  1143.             DReg := ToReg
  1144.         else
  1145.             AllocateDataRegister(DReg, Stacked); { will not happen with above }
  1146.         Evaluate(Right, DReg);
  1147.         if RangeCheck and (Left^.EType <> StringType) then begin
  1148.             Out_Operation1(op_PEA,3,ea_Absolute,a7);
  1149.             Out_Extension((Left^.EType^.Upper -
  1150.                    Left^.EType^.Lower) *
  1151.                    Left^.EType^.SubType^.Size);
  1152.             Out_Operation1(op_PUSH,4,ea_Register,DReg);
  1153.             Out_Operation1(op_JSR,3,ea_String,a7);
  1154.             Out_Extension(Integer("_p%CheckRange"));
  1155.         end;
  1156.         if SimpleType(EType) then begin
  1157.             Out_Operation2(op_MOVE,EType^.Size,ea_RegInd,AReg,
  1158.                             ea_Register,DReg);
  1159.             Out_Extension(Ord(DReg));
  1160.         end else begin
  1161.             if DReg = ToReg then
  1162.             Out_Operation2(op_ADD,4,ea_Register,AReg,
  1163.                             ea_Register,DReg)
  1164.             else
  1165.             Out_Operation2(op_ADDA,4,ea_Register,DReg,
  1166.                             ea_Register,AReg);
  1167.         end;
  1168.         if DReg = ToReg then
  1169.             DeallocateAddressRegister(AReg, Stacked)
  1170.         else
  1171.             DeallocateDataRegister(DReg, Stacked);
  1172.         end;
  1173.     end;
  1174.     end;
  1175.  
  1176.  
  1177.     Procedure Eval_Dereference;
  1178.     var
  1179.     OtherReg : Regs;
  1180.     Stacked  : Boolean;
  1181.     SaveUsed : Integer;
  1182.     begin
  1183.     with Expr^ do begin
  1184.         if Left^.EType^.Object = ob_file then begin
  1185.         SaveUsed := UsedRegs;
  1186.         SaveScratchRegisters;
  1187.         Evaluate(Left,a0);
  1188.         Out_Operation1(op_JSR,3,ea_String,a7);
  1189.         Out_Extension(Integer("_p%FilePtr"));
  1190.         if IOCheck then begin
  1191.             Out_Operation1(op_JSR,3,ea_String,a7);
  1192.             Out_Extension(Integer("_p%CheckIO"));
  1193.         end;
  1194.         Out_Operation2(op_MOVE,EType^.Size,ea_Indirect,a0,
  1195.                             ea_Register,ToReg);
  1196.         UsedRegs := SaveUsed;
  1197.         RestoreScratchRegisters;
  1198.         end else if SimpleType(EType) then begin
  1199.         if ToReg < a0 then
  1200.             AllocateAddressRegister(OtherReg, Stacked)
  1201.         else
  1202.             OtherReg := ToReg;
  1203.         Evaluate(Left, OtherReg);
  1204.         Out_Operation2(op_MOVE,EType^.Size,ea_Indirect,OtherReg,
  1205.                             ea_Register,ToReg);
  1206.         if ToReg < a0 then
  1207.             DeallocateAddressRegister(OtherReg, Stacked);
  1208.         end else
  1209.         Evaluate(Left, ToReg);
  1210.     end;
  1211.     end;
  1212.  
  1213.  
  1214.     Procedure Eval_RecordReference;
  1215.     var
  1216.     OtherReg : Regs;
  1217.     Stacked  : Boolean;
  1218.     begin
  1219.     with Expr^ do begin
  1220.         if SimpleType(EType) then begin
  1221.         if ToReg < a0 then
  1222.             AllocateAddressRegister(OtherReg, Stacked)
  1223.         else
  1224.             OtherReg := ToReg;
  1225.         EvalAddress(Left,OtherReg);
  1226.         Out_Operation2(op_MOVE,EType^.Size,ea_Index,OtherReg,
  1227.                             ea_Register,ToReg);
  1228.         Out_Extension(Value);
  1229.         if ToReg < a0 then
  1230.             DeallocateAddressRegister(OtherReg, Stacked);
  1231.         end else begin
  1232.         EvalAddress(Left,ToReg);
  1233.         AddConstant(Value, ToReg, 4);
  1234.         end;
  1235.     end;
  1236.     end;
  1237.  
  1238.  
  1239.     Procedure DoOpen(AccessMode : Short);
  1240.  
  1241.     {
  1242.     This routine handles both open and reopen, depending on the
  1243.     AccessMode sent to it.  This is just passed on to the DOS routine.
  1244.  
  1245.     OpenExpr:
  1246.         Kind: stanfunc1
  1247.         Value: 7 or 8 (reopen or open)
  1248.         Left Right
  1249.            /         \
  1250.           /           \
  1251.     File Var Expr      file name expr (string)
  1252.     Next
  1253.         \
  1254.          \
  1255.           Buffer Size
  1256.      }
  1257.  
  1258.     var
  1259.     BufferSize    : ExprPtr;
  1260.     SaveUsed    : Integer;
  1261.     begin
  1262.     SaveUsed := UsedRegs;
  1263.     SaveScratchRegisters;
  1264.     with Expr^.Right^ do begin
  1265.         if Kind = Const1 then begin
  1266.         Out_Operation1(op_PUSH,4,ea_Constant,a7);
  1267.         Out_Extension(Value);
  1268.         end else if Kind = Quote1 then begin
  1269.         Out_Operation1(op_PUSH,4,ea_Literal,a7);
  1270.         Out_Extension(Value);
  1271.         end else begin
  1272.         Evaluate(Expr^.Right, d0);
  1273.         Out_Operation1(op_PUSH,4,ea_Register,d0);
  1274.         UnmarkRegister(d0);
  1275.         end;
  1276.     end;
  1277.  
  1278.     StackLoad := StackLoad + 4;    
  1279.     Evaluate(Expr^.Left,a0);
  1280.  
  1281.     Out_Operation2(op_MOVE,2,ea_Constant,a7,ea_Index,a0);
  1282.     Out_Extension(AccessMode);
  1283.     Out_Extension(30);
  1284.  
  1285.     Out_Operation2(op_MOVE,4,ea_Constant,a7,ea_Index,a0);
  1286.     Out_Extension(Expr^.Left^.EType^.SubType^.Size);
  1287.     Out_Extension(24);
  1288.  
  1289.     BufferSize := Expr^.Left^.Next;
  1290.     if BufferSize^.Kind = Const1 then begin
  1291.         Out_Operation2(op_MOVE,4,ea_Constant,a7,ea_Index,a0);
  1292.         Out_Extension(BufferSize^.Value);
  1293.     end else if SimpleReference(BufferSize) then begin
  1294.         WriteSimpleSource(BufferSize,op_MOVE,4,ea_Index,a0);
  1295.     end else begin
  1296.         Evaluate(BufferSize,d0);
  1297.         Out_Operation2(op_MOVE,4,ea_Register,d0,ea_Index,a0);
  1298.     end;
  1299.     Out_Extension(20);
  1300.  
  1301.     Out_Operation1(op_PUSH,4,ea_Register,a0);
  1302.     Out_Operation1(op_JSR,3,ea_String,a7);
  1303.     Out_Extension(Integer("_p%Open"));
  1304.  
  1305.     if ToReg <> d0 then
  1306.         Out_Operation2(op_MOVE,1,ea_Register,d0,ea_Register,ToReg);
  1307.  
  1308.     AddConstant(8, a7, 4);
  1309.     StackLoad := StackLoad - 4;
  1310.  
  1311.     UsedRegs := SaveUsed;
  1312.     RestoreScratchRegisters;
  1313.     MathLoaded := False;
  1314.     end;
  1315.  
  1316.  
  1317.     Procedure Eval_StandardFunction;
  1318.     var
  1319.     Stacked  : Boolean;
  1320.     Lab      : Integer;
  1321.     STag     : Byte;
  1322.     SaveUsed : Integer;
  1323.     OtherReg : Regs;
  1324.     begin
  1325.     STag := Expr^.Left^.EType^.Size;
  1326.     case Expr^.Value of
  1327.     {Ord} 1,
  1328.     {Chr} 2,  : Evaluate(Expr^.Left,ToReg);
  1329.     {Odd} 3   : begin
  1330.             Evaluate(Expr^.Left,ToReg);
  1331.             ConstantOperation(op_AND,STag,1,ToReg);
  1332.             Out_Operation1(op_SNE,3,ea_Register,ToReg);
  1333.         end;
  1334.     {Abs} 4   : if Expr^.EType = RealType then begin
  1335.             Eval_UnaryFloat(-54);
  1336.         end else begin
  1337.             Lab := GetLabel;
  1338.             Evaluate(Expr^.Left, ToReg);
  1339.             Out_Operation1(op_TST,STag,ea_Register,ToReg);
  1340.             Out_Operation1(op_BPL,3,ea_Label,a7);
  1341.             Out_Extension(Lab);
  1342.             Out_Operation1(op_NEG,STag,ea_Register,ToReg);
  1343.             Out_Operation1(op_LABEL,3,ea_Label,a7);
  1344.             Out_Extension(Lab);
  1345.         end;
  1346.     {Succ} 5  : begin
  1347.             Evaluate(Expr^.Left,ToReg);
  1348.             AddConstant(1, ToReg, STag);
  1349.         end;
  1350.     {Pred} 6  : begin
  1351.             Evaluate(Expr^.Left,ToReg);
  1352.             AddConstant(-1, ToReg, STag);
  1353.         end;
  1354.     {ReOpen} 7 : DoOpen(1005);
  1355.     {Open}   8 : DoOpen(1006);
  1356.     {EOF} 9   : begin
  1357.             AllocateAddressRegister(OtherReg, Stacked);
  1358.             Evaluate(Expr^.Left,OtherReg);
  1359.             Out_Operation2(op_MOVE,1,ea_Index,OtherReg,
  1360.                         ea_Register,ToReg);
  1361.             Out_Extension(29);
  1362.             DeallocateAddressRegister(OtherReg, Stacked);
  1363.         end;
  1364.  {Trunc}  10  : Eval_UnaryFloat(-30);
  1365.  {Round}  11  : begin
  1366.             SaveUsed := UsedRegs;
  1367.             SaveScratchRegisters;
  1368.             Evaluate(Expr^.Left, d0);
  1369.             Out_Operation2(op_MOVE,4,ea_Constant,a7,ea_Register,d1);
  1370.             Out_Extension(Integer(0.5));
  1371.             if not MathLoaded then begin
  1372.             Out_Operation2(op_MOVE,4,ea_String,a7,ea_Register,a6);
  1373.             Out_Extension(Integer("_p%MathBase"));
  1374.             MathLoaded := True;
  1375.             end;
  1376.             Out_Operation1(op_JSR,3,ea_Index,a6);
  1377.             Out_Extension(-66);
  1378.             Out_Operation1(op_JSR,3,ea_Index,a6);
  1379.             Out_Extension(-90);
  1380.             Out_Operation1(op_JSR,3,ea_Index,a6);
  1381.             Out_Extension(-30);
  1382.             if ToReg <> d0 then
  1383.             Out_Operation2(op_MOVE,4,ea_Register,d0,
  1384.                             ea_Register,ToReg);
  1385.             UsedRegs := SaveUsed;
  1386.             RestoreScratchRegisters;
  1387.         end;
  1388.  { Float } 12 : Eval_UnaryFloat(-36);
  1389.  { Floor } 13 : Eval_UnaryFloat(-90);
  1390.  { Ceil }  14 : Eval_UnaryFloat(-96);
  1391.  { SizeOf }
  1392.  
  1393.  { Adr }   16 : EvalAddress(Expr^.Left, ToReg);
  1394.  { Bit }
  1395.  { Sqr }   18 : begin
  1396.             SaveUsed := UsedRegs;
  1397.             SaveScratchRegisters;
  1398.             Evaluate(Expr^.Left, d0);
  1399.             Out_Operation2(op_MOVE,4,ea_Register,d0,ea_Register,d1);
  1400.             if not MathLoaded then begin
  1401.             Out_Operation2(op_MOVE,4,ea_String,a7,ea_Register,a6);
  1402.             Out_Extension(Integer("_p%MathBase"));
  1403.             MathLoaded := True;
  1404.             end;
  1405.             Out_Operation1(op_JSR,3,ea_Index,a6);
  1406.             Out_Extension(-78);
  1407.             if ToReg <> d0 then
  1408.             Out_Operation2(op_MOVE,4,ea_Register,d0,
  1409.                             ea_Register,ToReg);
  1410.             UsedRegs := SaveUsed;
  1411.             RestoreScratchRegisters;
  1412.         end;
  1413.       19..25 : { Sqr, Sin, Cos, Sqrt, Tan, ArcTan, Ln, Exp }
  1414.         with Expr^ do begin
  1415.         SaveUsed := UsedRegs;
  1416.         SaveScratchRegisters;
  1417.         if Left^.Kind = Const1 then begin
  1418.             Out_Operation1(op_PEA,3,ea_Absolute,a7);
  1419.             Out_Extension(Expr^.Value);
  1420.         end else if SimpleReference(Expr) then begin
  1421.             WriteSimpleSingle(Expr,op_PUSH,4);
  1422.         end else begin
  1423.             Evaluate(Expr^.Left, ToReg);
  1424.             Out_Operation1(op_PUSH,4,ea_Register,ToReg);
  1425.         end;
  1426.         Out_Operation1(op_JSR,3,ea_String,a7);
  1427.         case Value of
  1428.           19 : Out_Extension(Integer("_p%sin"));
  1429.           20 : Out_Extension(Integer("_p%cos"));
  1430.           21 : Out_Extension(Integer("_p%sqrt"));
  1431.           22 : Out_Extension(Integer("_p%tan"));
  1432.           23 : Out_Extension(Integer("_p%atn"));
  1433.           24 : Out_Extension(Integer("_p%ln"));
  1434.           25 : Out_Extension(Integer("_p%exp"));
  1435.         end;
  1436.         AddConstant(4, a7, 4);
  1437.         if ToReg <> d0 then
  1438.             Out_Operation2(op_MOVE,4,ea_Register,d0,ea_Register,ToReg);
  1439.                 UsedRegs := SaveUsed;
  1440.                 RestoreScratchRegisters;
  1441.         end;
  1442.     end;
  1443.     end;
  1444.  
  1445.  
  1446.     Procedure Eval_FunctionCall;
  1447.     var
  1448.     SaveUsed : Integer;
  1449.     ID       : IDPtr;
  1450.     PushSize : Integer;
  1451.     begin
  1452.     SaveUsed := UsedRegs;
  1453.     SaveScratchRegisters;
  1454.     PushSize := PushArguments(Expr, ToReg);
  1455.     ID := IDPtr(Expr^.Value);
  1456.     PushSize := PushSize + PushFrame(ID^.Level);
  1457.     Out_Operation1(op_JSR,3,ea_Global,a7);
  1458.     Out_Extension(Integer(ID));
  1459.     PopStackSpace(PushSize);
  1460.     if ToReg <> d0 then
  1461.         Out_Operation2(op_MOVE,4,ea_Register,d0,ea_Register,ToReg);
  1462.     UsedRegs := SaveUsed;
  1463.     RestoreScratchRegisters;
  1464.     MathLoaded := False;
  1465.     end;
  1466.  
  1467.  
  1468.  
  1469.     Procedure Eval_FieldReference;
  1470.     var
  1471.     WithInfo : WithRecPtr;
  1472.     Stacked  : Boolean;
  1473.     STag     : Byte;
  1474.     OtherReg : Regs;
  1475.     ID       : IDPtr;
  1476.     begin
  1477.     ID := IDPtr(Expr^.Value);
  1478.     WithInfo := WithRecPtr(Expr^.Left);
  1479.     if SimpleType(Expr^.EType) then begin
  1480.         STag := ID^.VType^.Size;
  1481.         if ToReg < a0 then
  1482.         AllocateAddressRegister(OtherReg, Stacked)
  1483.         else
  1484.         OtherReg := ToReg;
  1485.         Out_Operation2(op_MOVE,4,ea_Index,a7,ea_Register,OtherReg);
  1486.         Out_Extension(StackLoad - WithInfo^.Offset);
  1487.  
  1488.         Out_Operation2(op_MOVE,STag,ea_Index,OtherReg,ea_Register,ToReg);
  1489.         Out_Extension(ID^.Offset);
  1490.         if ToReg < a0 then
  1491.         DeallocateAddressRegister(OtherReg, Stacked);
  1492.     end else begin
  1493.         Out_Operation2(op_MOVE,4,ea_Index,a7,ea_Register,ToReg);
  1494.         Out_Extension(StackLoad - WithInfo^.Offset);
  1495.         AddConstant(ID^.Offset, ToReg, 4);
  1496.     end;
  1497.     end;
  1498.  
  1499.  
  1500.  
  1501.     { Return the power of 2 represented by Value, or -1 if it's not
  1502.       a power of 2 }
  1503.  
  1504.     Function GetShifts(Value : Integer) : Integer;
  1505.     var
  1506.     Compare : Integer;
  1507.     Shifts  : Integer;
  1508.     begin
  1509.     Shifts := 0;
  1510.     Compare := 1;
  1511.     repeat
  1512.         if Compare = Value then
  1513.         GetShifts := Shifts;
  1514.         Inc(Shifts);
  1515.         Compare := Compare shl 1;
  1516.     until Shifts > 30;
  1517.     GetShifts := -1;
  1518.     end;
  1519.  
  1520.  
  1521.     Procedure Eval_Multiplier;
  1522.     var
  1523.     Shifts   : Integer;
  1524.     begin
  1525.     with Expr^ do begin
  1526.         if Left^.Kind = Const1 then begin
  1527.         Shifts := GetShifts(Left^.Value);
  1528.         if Shifts = 0 then begin
  1529.             Evaluate(PromoteTypeA(Right,IntType), ToReg);
  1530.             Return;
  1531.         end;
  1532.         if Shifts < 0 then begin
  1533.             if Left^.EType^.Size = 4 then
  1534.             Eval_32BitMath("_p%lmul")
  1535.             else
  1536.             Eval_BinaryMath(op_MULS,False);
  1537.         end else begin
  1538.             Evaluate(PromoteTypeA(Right,IntType), ToReg);
  1539.             ConstantShiftLeft(Shifts, ToReg, 4);
  1540.         end;
  1541.         end else begin
  1542.         if Left^.EType^.Size = 4 then
  1543.             Eval_32BitMath("_p%lmul")
  1544.         else
  1545.             Eval_BinaryMath(op_MULS,False);
  1546.         end;
  1547.     end;
  1548.     end;
  1549.  
  1550.  
  1551.     Procedure Eval_Divisor;
  1552.     var
  1553.     Shifts   : Integer;
  1554.     begin
  1555.     with Expr^ do begin
  1556.         if Left^.Kind = Const1 then begin
  1557.         Shifts := GetShifts(Left^.Value);
  1558.         if Shifts = 0 then begin
  1559.             Evaluate(Right, ToReg);
  1560.             Return;
  1561.         end;
  1562.         if Shifts < 0 then begin
  1563.             if Left^.EType^.Size = 4 then
  1564.             Eval_32BitMath("_p%ldiv")
  1565.             else
  1566.             Eval_BinaryMath(op_DIVS,False);
  1567.         end else begin
  1568.             Evaluate(Right, ToReg);
  1569.             ConstantShiftRight(op_ASR,Shifts, ToReg, 4);
  1570.         end;
  1571.         end else begin
  1572.         if Left^.EType^.Size = 4 then
  1573.             Eval_32BitMath("_p%ldiv")
  1574.         else
  1575.             Eval_BinaryMath(op_DIVS,False);
  1576.         end;
  1577.     end;
  1578.     end;
  1579.  
  1580.  
  1581.     Procedure Eval_Modulus;
  1582.     var
  1583.     Shifts   : Integer;
  1584.     begin
  1585.     with Expr^ do begin
  1586.         if Left^.Kind = Const1 then begin
  1587.         Shifts := GetShifts(Left^.Value);
  1588.         if Shifts = 0 then begin
  1589.             Out_Operation2(op_MOVE,4,ea_Constant,a7,ea_Register,ToReg);
  1590.             Out_Extension(0);
  1591.             Return;
  1592.         end;
  1593.         if Shifts < 0 then begin
  1594.             if Left^.EType^.Size = 4 then
  1595.             Eval_32BitMath("_p%lrem")
  1596.             else begin
  1597.             Eval_BinaryMath(op_DIVS,False);
  1598.             Out_Operation1(op_SWAP,3,ea_Register,ToReg);
  1599.             end;
  1600.         end else begin
  1601.             Evaluate(Right, ToReg);
  1602.             ConstantOperation(op_AND,Expr^.EType^.Size,
  1603.                     Pred(1 shl shifts), ToReg);
  1604.         end;
  1605.         end else begin
  1606.         if Left^.EType^.Size = 4 then
  1607.             Eval_32BitMath("_p%lrem")
  1608.         else begin
  1609.             Eval_BinaryMath(op_DIVS,False);
  1610.             Out_Operation1(op_SWAP,3,ea_Register,ToReg);
  1611.         end;
  1612.         end;
  1613.     end;
  1614.     end;
  1615.  
  1616.  
  1617. begin
  1618.     if Expr^.EType = BadType then
  1619.     return;
  1620.  
  1621.     op := Expr^.Kind;
  1622.     TagModel := ". \t";
  1623.  
  1624.     if op <= minus1 then begin
  1625.     if op <= xor1 then begin
  1626.         case op of
  1627.           and1    : if (Expr^.EType = BoolType) and ShortCircuit then
  1628.                   Eval_Boolean
  1629.               else
  1630.                   Eval_BinaryMath(op_AND,True);
  1631.           const1    : Eval_Constant;
  1632.           div1    : Eval_Divisor;
  1633.           func1    : Eval_FunctionCall;
  1634.           mod1    : Eval_Modulus;
  1635.           not1    : Eval_UnaryMath(op_NOT);
  1636.           or1    : if (Expr^.EType = BoolType) and ShortCircuit then
  1637.                   Eval_Boolean
  1638.               else
  1639.                   Eval_BinaryMath(op_OR,True);
  1640.           shl1    : Eval_Shift;
  1641.           shr1    : Eval_Shift;
  1642.           type1    : Evaluate(Expr^.Left, ToReg);
  1643.           var1    : LoadIDValue(IDPtr(Expr^.Value));
  1644.           xor1    : Eval_BinaryMath(op_EOR,True);
  1645.         else
  1646.         Writeln(OutFile, 'Did not do: ', Ord(op));
  1647.         end;
  1648.     end else begin
  1649.         case op of
  1650.           asterisk1    : if Expr^.EType = RealType then
  1651.                   Eval_BinaryFloat(-78)
  1652.               else
  1653.                   Eval_Multiplier;
  1654.           equal1    : Eval_Comparison;
  1655.           greater1    : Eval_Comparison;
  1656.           leftbrack1: Eval_ArrayReference;
  1657.           less1    : Eval_Comparison;
  1658.           minus1    : if Expr^.Right = Nil then begin { Unary minus }
  1659.                 if Expr^.EType = RealType then
  1660.                     Eval_UnaryFloat(-60)
  1661.                 else
  1662.                     Eval_UnaryMath(op_NEG);
  1663.               end else begin
  1664.                 if Expr^.EType = RealType then
  1665.                     Eval_BinaryFloat(-72)
  1666.                 else
  1667.                     Eval_BinaryMath(op_SUB,True);
  1668.               end;
  1669.         else
  1670.         Writeln(OutFile, 'Did not do ', Ord(op));
  1671.         end;
  1672.     end;
  1673.     end else begin
  1674.     if op <= carat1 then begin
  1675.         case op of
  1676.           notequal1    : Eval_Comparison;
  1677.           notgreater1 : Eval_Comparison;
  1678.           notless1    : Eval_Comparison;
  1679.           period1    : Eval_RecordReference;
  1680.           plus1    : if Expr^.EType = RealType then
  1681.                   Eval_BinaryFloat(-66)
  1682.               else
  1683.                   Eval_BinaryMath(op_ADD,True);
  1684.           quote1    : begin
  1685.                   Out_Operation2(op_MOVE,4,ea_Literal,a7,
  1686.                             ea_Register,ToReg);
  1687.                   Out_Extension(Expr^.Value);
  1688.               end;
  1689.           carat1    : Eval_Dereference;
  1690.         else
  1691.         Writeln(OutFile, 'Did not do ', Ord(op));
  1692.         end;
  1693.     end else begin
  1694.         case op of
  1695.           at1    : EvalAddress(Expr^.Left, ToReg);
  1696.           realdiv1 : Eval_BinaryFloat(-84);
  1697.           int2real : Eval_UnaryFloat(-36);
  1698.           real2int : Eval_UnaryFloat(-30);
  1699.           short2long : begin
  1700.                 Evaluate(Expr^.Left, ToReg);
  1701.                 Out_Operation1(op_EXT,4,ea_Register,ToReg);
  1702.                end;
  1703.           byte2short : begin
  1704.                 Evaluate(Expr^.Left, ToReg);
  1705.                 Out_Operation2(op_AND,2,ea_Constant,a7,
  1706.                             ea_Register,ToReg);
  1707.                 Out_Extension(255);
  1708.                end;
  1709.           byte2long    : begin
  1710.                   Evaluate(Expr^.Left, ToReg);
  1711.                   ConstantOperation(op_AND, 4, $FF, ToReg);
  1712.               end;
  1713.           stanfunc1 : Eval_StandardFunction;
  1714.           field1    : Eval_FieldReference;
  1715.         else
  1716.         Writeln(OutFile, 'Did not do ', Ord(op));
  1717.         end;
  1718.     end;
  1719.     end;
  1720.     MarkRegister(ToReg);
  1721. end;
  1722.  
  1723. {
  1724. Procedure ReportTree(Expr : ExprPtr);
  1725. var
  1726.     ID : IDPtr;
  1727.     E2 : ExprPtr;
  1728.     TP : TypePtr;
  1729. begin
  1730.     Write(OutFile, '(');
  1731.     case Expr^.Kind of
  1732.     const1 : if Expr^.EType = RealType then
  1733.              Write(OutFile, Real(Expr^.Value))
  1734.          else
  1735.              Write(OutFile, Expr^.Value);
  1736.     and1,
  1737.     div1,
  1738.     or1,
  1739.     shl1,
  1740.     shr1,
  1741.     xor1,
  1742.     asterisk1,
  1743.     equal1,
  1744.     notequal1,
  1745.     greater1,
  1746.     less1,
  1747.     notgreater1,
  1748.     notless1,
  1749.     plus1,
  1750.     realdiv1,
  1751.     mod1 : begin
  1752.            ReportTree(Expr^.Left);
  1753.            case Expr^.Kind of
  1754.              and1 : Write(OutFile, ' and ');
  1755.              div1 : Write(OutFile, ' div ');
  1756.              mod1 : Write(OutFile, ' mod ');
  1757.              or1  : Write(OutFile, ' or ');
  1758.              shl1 : Write(OutFile, ' shl ');
  1759.              shr1 : Write(OutFile, ' shr ');
  1760.              xor1 : Write(OutFile, ' xor ');
  1761.              asterisk1 : Write(OutFile, ' * ');
  1762.              equal1 : Write(OutFile, ' = ');
  1763.              notequal1 : Write(OutFile, ' <> ');
  1764.              greater1 : write(OutFile, ' > ');
  1765.              less1 : Write(OutFile, ' < ');
  1766.              notgreater1 : Write(OutFile, ' <= ');
  1767.              notless1 : Write(OutFile, ' >= ');
  1768.              plus1 : Write(OutFile, ' + ');
  1769.              minus1 : Write(OutFile, ' - ');
  1770.              realdiv1 : Write(OutFile, ' / ');
  1771.            end;
  1772.            ReportTree(Expr^.Right);
  1773.         end;
  1774.     minus1: if Expr^.Right = Nil then begin
  1775.             Write(OutFile, '-');
  1776.             ReportTree(Expr^.Left);
  1777.         end else begin
  1778.             ReportTree(Expr^.Left);
  1779.             Write(OutFile, ' - ');
  1780.             ReportTree(Expr^.Right);
  1781.         end;
  1782.     func1 : begin
  1783.             ID := IDPtr(Expr^.Value);
  1784.             Write(OutFile, ID^.Name, '(');
  1785.             E2 := Expr^.Left;
  1786.             while E2 <> Nil do begin
  1787.             ReportTree(E2);
  1788.             Write(OutFile, ',');
  1789.             E2 := E2^.Next;
  1790.             end;
  1791.             Write(OutFile, ')');
  1792.         end;
  1793.     not1: begin
  1794.         write(OutFile, ' not ');
  1795.         ReportTree(Expr^.Left);
  1796.           end;
  1797.     type1: begin
  1798.         write(OutFile, 'type(');
  1799.         ReportTree(Expr^.Left);
  1800.         Write(OutFile, ')');
  1801.            end;
  1802.     var1 : begin
  1803.             ID := IDPtr(Expr^.Value);
  1804.             case ID^.Object of
  1805.               global,
  1806.               typed_const : Write(OutFile, ID^.Name);
  1807.               local,
  1808.               refarg,
  1809.               valarg : Write(OutFile, ID^.Offset, '(a5)');
  1810.             else
  1811.                 Write(OutFile, 'var(', Ord(ID^.Object), ')');
  1812.             end;
  1813.         end;
  1814.     leftbrack1 :
  1815.         begin
  1816.             ReportTree(Expr^.Left);
  1817.             Write(OutFile, '[');
  1818.             ReportTree(Expr^.Right);
  1819.             Write(OutFile, ']');
  1820.         end;
  1821.     period1    :
  1822.         begin
  1823.             ReportTree(Expr^.Left);
  1824.             Write(OutFile, '.', Expr^.Value);
  1825.         end;
  1826.     quote1    : Write(OutFile, '""');
  1827.     carat1    : begin
  1828.             ReportTree(Expr^.Left);
  1829.             Write(OutFile, '^');
  1830.           end;
  1831.     at1    : begin
  1832.              Write(OutFile, '@');
  1833.              ReportTree(Expr^.Left);
  1834.          end;
  1835.     int2real : begin
  1836.             write(OutFile, '_float(');
  1837.             ReportTree(Expr^.Left);
  1838.             write(OutFile, ')');
  1839.            end;
  1840.     real2int : begin
  1841.             Write(OutFile, '_trunc(');
  1842.             ReportTree(Expr^.Left);
  1843.             Write(OutFile, ')');
  1844.            end;
  1845.     short2long : begin
  1846.             Write(OutFile, 'short2long(');
  1847.             ReportTree(Expr^.Left);
  1848.             Write(OutFile, ')');
  1849.             end;
  1850.     byte2short : begin
  1851.             Write(OutFile, 'byte2short(');
  1852.             ReportTree(Expr^.Left);
  1853.             Write(OutFile, ')');
  1854.              end;
  1855.     byte2long : begin
  1856.             Write(OutFile, 'byte2long(');
  1857.             ReportTree(Expr^.Left);
  1858.             Write(OutFile, ')');
  1859.             end;
  1860.     stanfunc1 : begin
  1861.             Write(OutFile, 'standard', Expr^.Value, '(');
  1862.             ReportTRee(Expr^.Left);
  1863.             Write(OutFile, ')');
  1864.             end;
  1865.     field1    : Write(OutFile, 'withfield');
  1866.     else
  1867.     Writeln(OutFile, 'Did not report ', Ord(Expr^.Kind));
  1868.     end;
  1869.     Write(OutFile, ')');
  1870. end;
  1871. }
  1872.  
  1873. Function Expression : TypePtr;
  1874. var
  1875.     Expr : ExprPtr;
  1876.     TP   : TypePtr;
  1877. begin
  1878.     NextFreeExprNode := 0;
  1879.     ConstantExpression := False;
  1880.     Expr := ExpressionTree;
  1881.     Optimize(Expr);
  1882.     TP := Expr^.EType;
  1883.     FreeAllRegisters;
  1884. {    if DoReport then begin
  1885.     ReportTree(Expr);
  1886.     Writeln(OutFile);
  1887.     end; }
  1888.     Evaluate(Expr,d0);
  1889.     NextFreeExprNode := 0;
  1890.     Expression := Expr^.EType;
  1891. end;
  1892.  
  1893. Function ConExpr(VAR ConType : TypePtr) : Integer;
  1894. var
  1895.     Expr : ExprPtr;
  1896.     Result : Integer;
  1897. begin
  1898.     NextFreeExprNode := 0;
  1899.     ConstantExpression := True;
  1900.     Expr := ExpressionTree;
  1901.     ConstantExpression := False;
  1902.     Optimize(Expr);
  1903.     Result := Expr^.Value;
  1904.     if (Expr^.Kind = Const1) or (Expr^.Kind = Quote1) then begin
  1905.     ConType := Expr^.EType;
  1906.     NextFreeExprNode := 0;
  1907.     ConExpr := Result;
  1908.     end else begin
  1909.     NextFreeExprNode := 0;
  1910.     ConType := BadType;
  1911.     Error("Expecting a Constant Expression");
  1912.     ConExpr := 1;
  1913.     end;
  1914. end;
  1915.  
  1916.  
  1917. {
  1918.     Store the result of the expression Expr in the address Destination.
  1919.     The two expressions must pass TypeCheck, or this will not work at all.
  1920. }
  1921.  
  1922. Procedure StoreValue(Expr : ExprPtr; Destination : ExprPtr);
  1923. var
  1924.     STag : Byte;
  1925.     SameType : Boolean;
  1926.     Lab  : Integer;
  1927.     OtherReg : Regs;
  1928. begin
  1929.     STag := Destination^.EType^.Size;
  1930.     SameType := STag = Expr^.EType^.Size;
  1931.     if SimpleReference(Destination) then begin
  1932.     if Expr^.Kind = Const1 then begin
  1933.         OtherReg := TemporaryData;
  1934.         with Expr^ do begin
  1935.         if (OtherReg < a0) and (STag = 4) and (Value <= 127) and
  1936.             (Value >= -128) and (Value <> 0) then begin
  1937.             Out_Operation2(op_MOVEQ,3,ea_Constant,a7,
  1938.                         ea_Register,OtherReg);
  1939.             Out_Extension(Value);
  1940.             WriteSimpleDest(Destination,op_MOVE,4,
  1941.                         ea_Register,OtherReg,0,0);
  1942.         end else
  1943.             WriteSimpleDest(Destination,op_MOVE,STag,
  1944.                         ea_Constant,a7,Value,0);
  1945.         end;
  1946.     end else begin
  1947.         Evaluate(Expr,d0);
  1948.         WriteSimpleDest(Destination,op_MOVE,STag,ea_Register,d0,0,0);
  1949.     end;
  1950.     end else if SimpleType(Destination^.EType) then begin
  1951.     EvalAddress(Destination,a0);
  1952.     if Expr^.Kind = Const1 then begin
  1953.         Out_Operation2(op_MOVE,STag,ea_Constant,a7,ea_Indirect,a0);
  1954.         Out_Extension(Expr^.Value);
  1955.     end else if SimpleReference(Expr) and SameType then begin
  1956.         WriteSimpleSource(Expr,op_MOVE,STag,ea_Indirect,a0);
  1957.     end else begin
  1958.         Evaluate(Expr, d0);
  1959.         Out_Operation2(op_MOVE,STag,ea_Register,d0,ea_Indirect,a0);
  1960.     end;
  1961.     end else begin
  1962.     Evaluate(Expr,a0);
  1963.     EvalAddress(Destination,a1);
  1964.  
  1965.     Out_Operation2(op_MOVE,4,ea_Constant,a7,ea_Register,d1);
  1966.     Out_Extension(Pred(Destination^.EType^.Size));
  1967.  
  1968.     lab := GetLabel();
  1969.     Out_Operation1(op_LABEL,3,ea_Label,a7);
  1970.     Out_Extension(Lab);
  1971.     Out_Operation2(op_MOVE,1,ea_PostInc,a0,ea_PostInc,a1);
  1972.     Out_Operation2(op_DBRA,3,ea_Register,d1,ea_Label,a7);
  1973.     Out_Extension(Lab);
  1974.     end;
  1975. end;
  1976.  
  1977. Procedure Assignment;
  1978. {
  1979.     Not surprisingly, this routine handles assignments.
  1980. }
  1981. var
  1982.     Destination,
  1983.     Expr    : ExprPtr;
  1984. begin
  1985.     NextFreeExprNode := 0;
  1986.     FreeAllRegisters;
  1987.     Destination := GetReference;
  1988.     if not Match(becomes1) then begin
  1989.     Error("Expecting :=");
  1990.     return;
  1991.     end;
  1992.     Optimize(Destination);
  1993. {    if DoReport then begin
  1994.     ReportTree(Destination);
  1995.     writeln(OutFile);
  1996.     end; }
  1997.     Expr := ExpressionTree;
  1998.     if NumberType(Destination^.EType) then begin
  1999.     Expr := PromoteTypeA(Expr, Destination^.EType);
  2000.     if (Expr^.EType = RealType) and
  2001.         (Destination^.EType^.Object = ob_ordinal) then
  2002.         Expr := MakeNode(real2int, Expr, Nil, IntType, 0);
  2003.     end;
  2004. {    if DoReport then begin
  2005.     ReportTree(Expr);
  2006.     Writeln(OutFile);
  2007.     end; }
  2008.     Optimize(Expr);
  2009. {    if DoReport then begin
  2010.     ReportTree(Expr);
  2011.     Writeln(OutFile);
  2012.     end; }
  2013.  
  2014.     if TypeCheck(Destination^.EType, Expr^.EType) then
  2015.     StoreValue(Expr, Destination)
  2016.     else
  2017.     Error("Mismatched Types in Assignment");
  2018. end;
  2019.